#include "cloud_config.h"
#include <QDir>
#include <QCoreApplication>
#include <QStandardPaths>
#include<QJsonDocument>
#include<QJsonArray>
#include <QDebug>
#include "common.h"
#include "enum_file.h"
#include "confighandler.h"
#include <QElapsedTimer>

using namespace std;

CloudConfig::CloudConfig()
{
    m_reply = nullptr;
}

CloudConfig::~CloudConfig()
{

}

template<typename T>
void CloudConfig::readConfig(QSettings* setting, T& map, T& mapOverseas, \
    const QString& groupName, const QString& key)
{
    map[groupName][key] = \
            common::decrypt(setting->value(key).toByteArray());
    mapOverseas[groupName][OVERSEAS(key)] = \
            common::decrypt(setting->value(OVERSEAS(key)).toByteArray());
}

void CloudConfig::readConfig()
{
    QString cfgPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/environment.ini";
    QFile configFile(cfgPath);
    if(!configFile.exists()) {
        QFile::copy(QCoreApplication::applicationDirPath() + "/environment.ini", \
        cfgPath);
    }

    m_setting = new QSettings(cfgPath, QSettings::IniFormat, this);
    // 获取版本
    m_setting->beginGroup(ENVIRONMENT_GROUP);
    qDebug() << m_setting->value(KEY_VERSION).toString();
    m_curVersion = QVersionNumber::fromString(m_setting->value(KEY_VERSION).toString());
    m_setting->endGroup();

    // 云API
    bool bTestServer = GlobalConfig::GetInstance()->readConfig(CommonEnum::BASE_TEST_ENVIRONMENT).toBool();
    m_groupName = bTestServer ? CLOUD_API_TEST_GROUP : CLOUD_API_PROD_GROUP;
    qInfo() << QString("current server is testserver. %1").arg(bTestServer);
    m_setting->beginGroup(m_groupName);
    readConfig(m_setting, m_cloudMap, m_cloudMapOverseas, m_groupName, GA_REPORTER);
    readConfig(m_setting, m_cloudMap, m_cloudMapOverseas, m_groupName, GA_REGION);
    readConfig(m_setting, m_cloudMap, m_cloudMapOverseas, m_groupName, CLOUD_API);
    readConfig(m_setting, m_cloudMap, m_cloudMapOverseas, m_groupName, AUTO_UPDATE);
    readConfig(m_setting, m_cloudMap, m_cloudMapOverseas, m_groupName, AUTO_UPDATE_MAC);
    readConfig(m_setting, m_cloudMap, m_cloudMapOverseas, m_groupName, PRIVACY);
    readConfig(m_setting, m_cloudMap, m_cloudMapOverseas, m_groupName, USERAGREEMENT);
    readConfig(m_setting, m_cloudMap, m_cloudMapOverseas, m_groupName, QCODE_ANDROID);
    readConfig(m_setting, m_cloudMap, m_cloudMapOverseas, m_groupName, QCODE_IOS);
    readConfig(m_setting, m_cloudMap, m_cloudMapOverseas, m_groupName, ABOUT_US);
    m_setting->endGroup();
}

void CloudConfig::initCloudData()
{
    QElapsedTimer time;
    time.start();
    readConfig();
    QByteArray cloudApi = GlobalConfig::GetInstance()->readConfig(CommonEnum::BASE_ENVIRONMENT).toByteArray();
    if(!cloudApi.isEmpty()) {
        QString url = common::decrypt(cloudApi);
        qInfo() << QString("environment_url is %1").arg(url);
        m_reply = m_networkAccessManager.get(QNetworkRequest(QUrl(url)));
        connect(m_reply, &QNetworkReply::finished, \
            this, &CloudConfig::networkFinisheded);
    }
    qInfo() << "QmlFactory" << time.elapsed()/1000.0 <<"s";
}

QVariant CloudConfig::cloudApi(CommonEnum::CloudUrl type)
{
    switch(type) {
    case CommonEnum::CLOUD_REPORTER:
        return m_cloudMap[m_groupName][GA_REPORTER];
    case CommonEnum::CLOUD_REPORTER_OVERSEAS:
        return m_cloudMapOverseas[m_groupName][OVERSEAS(GA_REPORTER)];
    case CommonEnum::CLOUD_REGION:
        return m_cloudMap[m_groupName][GA_REGION];
    case CommonEnum::CLOUD_REGION_OVERSEAS:
        return m_cloudMapOverseas[m_groupName][OVERSEAS(GA_REGION)];
    case CommonEnum::CLOUD_INTERFACE:
        return m_cloudMap[m_groupName][CLOUD_API];
    case CommonEnum::CLOUD_INTERFACE_OVERSEAS:
        return m_cloudMapOverseas[m_groupName][OVERSEAS(CLOUD_API)];
    case CommonEnum::CLOUD_QCODE_ANDROID:
        return m_cloudMap[m_groupName][QCODE_ANDROID];
    case CommonEnum::CLOUD_QCODE_ANDROID_OVERSEAS:
        return m_cloudMapOverseas[m_groupName][OVERSEAS(QCODE_ANDROID)];
    case CommonEnum::CLOUD_QCODE_IOS:
        return m_cloudMap[m_groupName][QCODE_IOS];
    case CommonEnum::CLOUD_QCODE_IOS_OVERSEAS:
        return m_cloudMapOverseas[m_groupName][OVERSEAS(QCODE_IOS)];
    case CommonEnum::CLOUD_PRIVACY:
        return m_cloudMap[m_groupName][PRIVACY];
    case CommonEnum::CLOUD_PRIVACY_OVERSEAS:
        return m_cloudMapOverseas[m_groupName][OVERSEAS(PRIVACY)];
    case CommonEnum::CLOUD_USERAGREEMENT:
        return m_cloudMap[m_groupName][USERAGREEMENT];
    case CommonEnum::CLOUD_USERAGREEMENT_OVERSEAS:
        return m_cloudMapOverseas[m_groupName][OVERSEAS(USERAGREEMENT)];
    case CommonEnum::CLOUD_ABOUTUS:
        return m_cloudMap[m_groupName][ABOUT_US];
    case CommonEnum::CLOUD_ABOUTUS_OVERSEAS:
        return m_cloudMapOverseas[m_groupName][OVERSEAS(ABOUT_US)];
    default:
        break;
    }

    return QVariant();
}

void CloudConfig::networkFinisheded()
{
    if(m_reply == nullptr || m_reply->error() != QNetworkReply::NoError)
        return;

    QByteArray recvData = m_reply->readAll();
    m_reply->deleteLater();
    m_reply = nullptr;

    if(recvData.isEmpty())
        return;

    QString cfgPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/environment.ini";
    QString downloadPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/environment_download.ini";
    QFile file(downloadPath);
    if(!file.open(QIODevice::ReadWrite)){
        return;
    }

    file.write(recvData);
    file.close();

    QSettings setting(downloadPath, QSettings::IniFormat);
    setting.beginGroup(ENVIRONMENT_GROUP);
    qDebug() << setting.value(KEY_VERSION).toString();
    QVersionNumber onlineVersion = QVersionNumber::fromString(setting.value(KEY_VERSION).toString());
    setting.endGroup();

    if(m_curVersion < onlineVersion) {
        QFile::remove(cfgPath);
        QFile::rename(downloadPath, cfgPath);
    } else
        QFile::remove(downloadPath);
}

